<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="keywords" content="技术,分享,生活">
    <meta name="description" content="这里是anlondon,欢迎留言交流">
    <meta name="author" content="anlondon">
    
    <title>
        
            php yield理解 |
        
        一座浮岛
    </title>
    
<link rel="stylesheet" href="/css/style.css">

    <link rel="shortcut icon" href="/images/logo_my.png">
    
<link rel="stylesheet" href="/fontawesome/css/fontawesome.min.css">

    
<link rel="stylesheet" href="/fontawesome/css/regular.min.css">

    
<link rel="stylesheet" href="/fontawesome/css/solid.min.css">

    
<link rel="stylesheet" href="/fontawesome/css/brands.min.css">

    <script id="hexo-configurations">
    let KEEP = window.KEEP || {};
    KEEP.hexo_config = {"hostname":"example.com","root":"/","language":"en","path":"search.json"};
    KEEP.theme_config = {"toc":{"enable":true,"number":true,"expand_all":true,"init_open":true},"style":{"primary_color":"#557ea2","logo":"/images/logo_my.png","favicon":"/images/logo_my.png","avatar":"/images/avatar_my.svg","font_size":null,"font_family":"STKaiti","hover":{"shadow":true,"scale":true},"first_screen":{"enable":true,"header_transparent":false,"background_img":"https://api.likepoems.com/img/nature","description":null,"font_color":null,"hitokoto":true},"scroll":{"progress_bar":false,"percent":false}},"local_search":{"enable":true,"preload":true},"code_copy":{},"code_block":{"tools":{"enable":true,"style":"default"},"highlight_theme":"obsidian"},"side_tools":{},"pjax":{"enable":true},"lazyload":{"enable":true},"comment":{"enable":true,"use":"valine","valine":{"appid":"v7SvjMu6zFX3LPmiYGos39qx-gzGzoHsz","appkey":"MlLOMElKkabjL3SHiqXhFWAW","placeholder":null},"gitalk":{"github_id":null,"github_admins":null,"repository":null,"client_id":null,"client_secret":null},"twikoo":{"env_id":null,"region":null,"version":"1.6.7"},"waline":{"server_url":null,"reaction":false,"version":2}},"post":{"author_label":{"enable":true,"auto":true,"custom_label_list":["Trainee","Engineer","Architect"]},"word_count":{"enable":true,"wordcount":true,"min2read":true},"img_align":"left","copyright_info":false},"version":"3.5.2"};
    KEEP.language_ago = {"second":"%s seconds ago","minute":"%s minutes ago","hour":"%s hours ago","day":"%s days ago","week":"%s weeks ago","month":"%s months ago","year":"%s years ago"};
    KEEP.language_code_block = {"copy":"Copy code","copied":"Copied","fold":"Fold code block","folded":"Folded"};
  </script>
<meta name="generator" content="Hexo 5.4.0"></head>


<body>
<!-- anlondon 加的 start -->
<div class="background-my"></div>
<!-- anlondon 加的 end-->
<div class="progress-bar-container">
    

    
        <span class="pjax-progress-bar"></span>
        <i class="pjax-progress-icon fas fa-circle-notch fa-spin"></i>
    
</div>


<main class="page-container">

    

    <div class="page-main-content">

        <div class="page-main-content-top">
            
<header class="header-wrapper">

    <div class="header-content">
        <div class="left">
            
                <a class="logo-image" href="/">
                    <img src="/images/logo_my.png">
                </a>
            
            <a class="logo-title" href="/">
               一座浮岛
            </a>
        </div>

        <div class="right">
            <div class="pc">
                <ul class="menu-list">
                    
                        <li class="menu-item">
                            <a class=""
                               href="/"
                            >
                                首页
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/archives"
                            >
                                时间流
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/categories"
                            >
                                归档
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/links"
                            >
                                LINKS
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/about"
                            >
                                关于
                            </a>
                        </li>
                    
                    
                        <li class="menu-item search search-popup-trigger">
                            <i class="fas fa-search"></i>
                        </li>
                    
                </ul>
            </div>
            <div class="mobile">
                
                    <div class="icon-item search search-popup-trigger"><i class="fas fa-search"></i></div>
                
                <div class="icon-item menu-bar">
                    <div class="menu-bar-middle"></div>
                </div>
            </div>
        </div>
    </div>

    <div class="header-drawer">
        <ul class="drawer-menu-list">
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/">首页</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/archives">时间流</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/categories">归档</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/links">LINKS</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/about">关于</a>
                </li>
            
        </ul>
    </div>

    <div class="window-mask"></div>

</header>


        </div>

        <div class="page-main-content-middle">

            <div class="main-content">

                
                    <div class="fade-in-down-animation">
    <div class="post-page-container">
        <div class="article-content-container">

            <div class="article-title">
                <span class="title-hover-animation">php yield理解</span>
            </div>

            
                <div class="article-header">
                    <div class="avatar">
                        <img src="/images/avatar_my.svg">
                    </div>
                    <div class="info">
                        <div class="author">
                            <span class="name">anlondon</span>
                            
                                <span class="author-label">Lv6</span>
                            
                        </div>
                        <div class="meta-info">
                            
<div class="article-meta-info">
    <span class="article-date article-meta-item">
        
            <i class="fa-regular fa-calendar-plus"></i>&nbsp;
        
        <span class="pc">2021-06-20 18:57:00</span>
        <span class="mobile">2021-06-20 18:57</span>
    </span>
    
        <span class="article-update-date article-meta-item">
        <i class="fas fa-file-pen"></i>&nbsp;
        <span class="pc">2021-08-25 13:59:27</span>
    </span>
    
    
        <span class="article-categories article-meta-item">
            <i class="fas fa-folder"></i>&nbsp;
            <ul>
                
                    <li>
                        <a href="/categories/PHP/">PHP</a>&nbsp;
                    </li>
                
            </ul>
        </span>
    
    
        <span class="article-tags article-meta-item">
            <i class="fas fa-tags"></i>&nbsp;
            <ul>
                
                    <li>
                        <a href="/tags/PHP/">PHP</a>&nbsp;
                    </li>
                
            </ul>
        </span>
    

    
    
    
    
        <span class="article-pv article-meta-item">
            <i class="fas fa-eye"></i>&nbsp;<span id="busuanzi_value_page_pv"></span>
        </span>
    
</div>

                        </div>
                    </div>
                </div>
            

            <div class="article-content keep-markdown-body">
                <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><blockquote>
<p>转载自：<a class="link"   target="_blank" rel="noopener" href="https://segmentfault.com/a/1190000012334856" >PHP中被忽略的性能优化利器：生成器|segmentfault<i class="fas fa-external-link-alt"></i></a><br>作者：<a class="link"   target="_blank" rel="noopener" href="https://segmentfault.com/u/yanying" >星空幻颖
 <i class="fas fa-external-link-alt"></i></a></p>
</blockquote>
<p>如果是做Python或者其他语言的小伙伴，对于生成器应该不陌生。但很多PHP开发者或许都不知道生成器这个功能，可能是因为生成器是PHP 5.5.0才引入的功能，也可以是生成器作用不是很明显。但是，生成器功能的确非常有用。</p>
<h4 id="优点"><a href="#优点" class="headerlink" title="优点"></a>优点</h4><hr>
<p>直接讲概念估计你听完还是一头雾水，所以我们先来说说优点，也许能勾起你的兴趣。那么生成器有哪些优点，如下：</p>
<ul>
<li>生成器会对PHP应用的性能有非常大的影响</li>
<li>PHP代码运行时节省大量的内存</li>
<li>比较适合计算大量的数据</li>
</ul>
<p>那么，这些神奇的功能究竟是如何做到的？我们先来举个例子。</p>
<h4 id="概念引入"><a href="#概念引入" class="headerlink" title="概念引入"></a>概念引入</h4><hr>
<p>首先，放下生成器概念的包袱，来看一个简单的PHP函数：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createRange</span>(<span class="params"><span class="variable">$number</span></span>)</span>&#123;</span><br><span class="line">    <span class="variable">$data</span> = [];</span><br><span class="line">    <span class="keyword">for</span>(<span class="variable">$i</span>=<span class="number">0</span>;<span class="variable">$i</span>&lt;<span class="variable">$number</span>;<span class="variable">$i</span>++)&#123;</span><br><span class="line">        <span class="variable">$data</span>[] = time();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="variable">$data</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这是一个非常常见的PHP函数，我们在处理一些数组的时候经常会使用。这里的代码也非常简单：</p>
<ul>
<li>我们创建一个函数。</li>
<li>函数内包含一个<code>for</code> 循环，我们循环的把当前时间放到<code>$data</code>里面</li>
<li><code>for</code>循环执行完毕，把 <code>$data</code> 返回出去。</li>
</ul>
<p>下面没完，我们继续。我们再写一个函数，把这个函数的返回值循环打印出来：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$result</span> = createRange(<span class="number">10</span>); <span class="comment">// 这里调用上面我们创建的函数</span></span><br><span class="line"><span class="keyword">foreach</span>(<span class="variable">$result</span> <span class="keyword">as</span> <span class="variable">$value</span>)&#123;</span><br><span class="line">    sleep(<span class="number">1</span>);<span class="comment">//这里停顿1秒，我们后续有用</span></span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$value</span>.<span class="string">&#x27;&lt;br /&gt;&#x27;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><img  
                     lazyload
                     alt="image"
                     data-src="/2021/06/20/php-yield%E7%90%86/pasted-1.png"
                      alt="一座浮岛"
                ></p>
<p>这里非常完美，没有任何问题。（当然 <code>sleep(1)</code> 效果你们看不出来）</p>
<h4 id="思考一个问题"><a href="#思考一个问题" class="headerlink" title="思考一个问题"></a>思考一个问题</h4><hr>
<p>我们注意到，在调用函数 <u><code>createRange</code> 的时候给 <code>$number</code> 的传值是10，一个很小的数字。<strong>假设，现在传递一个值<code>10000000</code>（1000万）。</strong></u></p>
<p>那么，在函数 <code>createRange</code> 里面，<u><code>for</code>循环就需要执行<code>1000</code>万次。且有<code>1000</code>万个值被放到 <code>$data</code> 里面，而<code>$data</code>数组在是被放在内存内。所以，在<strong>调用函数时候会占用大量内存</strong>。</u></p>
<p>这里，生成器就可以大显身手了。</p>
<h4 id="创建生成器"><a href="#创建生成器" class="headerlink" title="创建生成器"></a>创建生成器</h4><hr>
<p>我们直接修改代码，你们注意观察：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createRange</span>(<span class="params"><span class="variable">$number</span></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">for</span>(<span class="variable">$i</span>=<span class="number">0</span>;<span class="variable">$i</span>&lt;<span class="variable">$number</span>;<span class="variable">$i</span>++)&#123;</span><br><span class="line">        <span class="keyword">yield</span> time();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>看下这段和刚刚很像的代码，我们删除了数组 <code>$data</code> ，而且也<strong>没有返回任何内容</strong>，而是在 <code>time()</code> <u>之前使用了一个关键字<code>yield</code>。</u></p>
<h4 id="使用生成器"><a href="#使用生成器" class="headerlink" title="使用生成器"></a>使用生成器</h4><hr>
<p>我们再运行一下第二段代码：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$result</span> = createRange(<span class="number">10</span>); <span class="comment">// 这里调用上面我们创建的函数</span></span><br><span class="line"><span class="keyword">foreach</span>(<span class="variable">$result</span> <span class="keyword">as</span> <span class="variable">$value</span>)&#123;</span><br><span class="line">    sleep(<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$value</span>.<span class="string">&#x27;&lt;br /&gt;&#x27;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><img  
                     lazyload
                     alt="image"
                     data-src="/2021/06/20/php-yield%E7%90%86/pasted-3.png"
                      alt="一座浮岛"
                ></p>
<p>我们奇迹般的发现了，输出的值和第一次没有使用生成器的不一样。这里的值（时间戳）中间间隔了1秒。</p>
<p>这里的间隔一秒其实就是 <code>sleep(1)</code> 造成的后果。但是为什么第一次没有间隔？那是因为：</p>
<ul>
<li>未使用生成器时： <code>createRange</code> 函数内的 <code>for</code> 循环结果被很快放到 <code>$data</code> 中，并且立即返回。所以， <code>foreach</code> 循环的是一个固定的数组。</li>
<li>使用生成器时： <code>createRange</code> 的值不是一次性快速生成，而是<u>依赖于 <code>foreach</code> 循环。 <code>foreach</code> 循环一次， <code>for</code> 执行一次。</u></li>
</ul>
<p>到这里，你应该对生成器有点儿头绪。</p>
<h4 id="深入理解生成器"><a href="#深入理解生成器" class="headerlink" title="深入理解生成器"></a>深入理解生成器</h4><hr>
<h6 id="代码剖析"><a href="#代码剖析" class="headerlink" title="代码剖析"></a>代码剖析</h6><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createRange</span>(<span class="params"><span class="variable">$number</span></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">for</span>(<span class="variable">$i</span>=<span class="number">0</span>;<span class="variable">$i</span>&lt;<span class="variable">$number</span>;<span class="variable">$i</span>++)&#123;</span><br><span class="line">        <span class="keyword">yield</span> time();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="variable">$result</span> = createRange(<span class="number">10</span>); <span class="comment">// 这里调用上面我们创建的函数</span></span><br><span class="line"><span class="keyword">foreach</span>(<span class="variable">$result</span> <span class="keyword">as</span> <span class="variable">$value</span>)&#123;</span><br><span class="line">    sleep(<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$value</span>.<span class="string">&#x27;&lt;br /&gt;&#x27;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>我们来还原一下代码执行过程。</p>
<ul>
<li>首先调用 <code>createRange</code> 函数，传入参数10，但是 <code>for</code> 值执行了一次然后停止了，并且告诉 foreach 第一次循环可以用的值。</li>
<li><code>foreach</code> 开始对 <code>$result</code> 循环，进来首先 <code>sleep(1)</code> ，然后开始使用 <code>for</code>给的一个值执行输出。</li>
<li><code>foreach</code> 准备第二次循环，开始第二次循环之前，它向 <code>for</code> 循环又请求了一次。</li>
<li><code>for</code> 循环于是又执行了一次，将生成的时间戳告诉 <code>foreach</code>.</li>
<li><code>foreach</code> 拿到第二个值，并且输出。由于 <code>foreach</code> 中 <code>sleep(1)</code> ，所以， <code>for</code> 循环延迟了1秒生成当前时间</li>
</ul>
<p>所以，整个代码执行中，始终只有一个记录值参与循环，内存中也只有一条信息。</p>
<p>无论开始传入的 <u><code>$number</code> 有多大，由于并不会立即生成所有结果集，所以内存始终是一条循环的值。</u></p>
<h4 id="概念理解"><a href="#概念理解" class="headerlink" title="概念理解"></a>概念理解</h4><p>到这里，你应该已经大概理解什么是生成器了。下面我们来说下生成器原理。</p>
<p>首先明确一个概念：<strong>生成器yield关键字不是返回值，他的专业术语叫产出值，只是生成一个值</strong></p>
<p>那么代码中 <code>foreach</code> 循环的是什么？<u>其实是PHP在使用生成器的时候，会返回一个 <code>Generator</code> 类的对象。 <code>foreach</code> 可以对该对象进行迭代，每一次迭代，PHP会通过 <code>Generator</code> 实例计算出下一次需要迭代的值。</u>这样 <code>foreach</code> 就知道下一次需要迭代的值了。</p>
<p>而且，在运行中 <u><code>for</code> 循环执行后，会立即停止。等待 <code>foreach</code> 下次循环时候再次和  <code>for</code>  索要下次的值的时候，循环才会再执行一次，然后立即再次停止。直到不满足条件不执行结束。</u></p>
<h4 id="实际开发应用"><a href="#实际开发应用" class="headerlink" title="实际开发应用"></a>实际开发应用</h4><p>很多PHP开发者不了解生成器，其实主要是不了解应用领域。那么，生成器在实际开发中有哪些应用？</p>
<h6 id="读取超大文件"><a href="#读取超大文件" class="headerlink" title="读取超大文件"></a>读取超大文件</h6><p>PHP开发很多时候都要读取大文件，比如csv文件、text文件，或者一些日志文件。这些文件如果很大，比如5个G。这时，直接一次性把所有的内容读取到内存中计算不太现实。</p>
<p>这里生成器就可以派上用场啦。简单看个例子：读取text文件</p>
<p><img  
                     lazyload
                     alt="image"
                     data-src="/2021/06/20/php-yield%E7%90%86/pasted-4.png"
                      alt="一座浮岛"
                ></p>
<p>我们创建一个text文本文档，并在其中输入几行文字，示范读取。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line">header(<span class="string">&quot;content-type:text/html;charset=utf-8&quot;</span>);</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">readTxt</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment"># code...</span></span><br><span class="line">    <span class="variable">$handle</span> = fopen(<span class="string">&quot;./test.txt&quot;</span>, <span class="string">&#x27;rb&#x27;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span> (feof(<span class="variable">$handle</span>)===<span class="literal">false</span>) &#123;</span><br><span class="line">        <span class="comment"># code...</span></span><br><span class="line">        <span class="keyword">yield</span> fgets(<span class="variable">$handle</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    fclose(<span class="variable">$handle</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">foreach</span> (readTxt() <span class="keyword">as</span> <span class="variable">$key</span> =&gt; <span class="variable">$value</span>) &#123;</span><br><span class="line">    <span class="comment"># code...</span></span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$value</span>.<span class="string">&#x27;&lt;br /&gt;&#x27;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><img  
                     lazyload
                     alt="image"
                     data-src="/2021/06/20/php-yield%E7%90%86/pasted-5.png"
                      alt="一座浮岛"
                ></p>
<p>通过上图的输出结果我们可以看出代码完全正常。</p>
<p>但是，背后的代码执行规则却一点儿也不一样。使用生成器读取文件，第一次读取了第一行，第二次读取了第二行，以此类推，<strong>每次被加载到内存中的文字只有一行</strong>，大大的减小了内存的使用。</p>
<p>这样，即使读取上G的文本也不用担心，完全可以像读取很小文件一样编写代码。</p>
<p>完</p>
<h4 id="补充"><a href="#补充" class="headerlink" title="补充"></a>补充</h4><hr>
<p><strong>百万级别的访问量</strong></p>
<p>yield生成器是php5.5之后出现的，yield提供了一种更容易的方法来实现简单的迭代对象，相比较定义类实现 Iterator 接口的方式，性能开销和复杂性大大降低。</p>
<p>yield生成器允许你 在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组。</p>
<p>使用示例：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">/** </span></span><br><span class="line"><span class="comment"> * 计算平方数列 </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> $start </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> $stop </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> Generator </span></span><br><span class="line"><span class="comment"> */</span>  </span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">squares</span>(<span class="params"><span class="variable">$start</span>, <span class="variable">$stop</span></span>) </span>&#123;  </span><br><span class="line">    <span class="keyword">if</span> (<span class="variable">$start</span> &lt; <span class="variable">$stop</span>) &#123;  </span><br><span class="line">        <span class="keyword">for</span> (<span class="variable">$i</span> = <span class="variable">$start</span>; <span class="variable">$i</span> &lt;= <span class="variable">$stop</span>; <span class="variable">$i</span>++) &#123;  </span><br><span class="line">            <span class="keyword">yield</span> <span class="variable">$i</span> =&gt; <span class="variable">$i</span> * <span class="variable">$i</span>;  </span><br><span class="line">        &#125;  </span><br><span class="line">    &#125;  </span><br><span class="line">    <span class="keyword">else</span> &#123;  </span><br><span class="line">        <span class="keyword">for</span> (<span class="variable">$i</span> = <span class="variable">$start</span>; <span class="variable">$i</span> &gt;= <span class="variable">$stop</span>; <span class="variable">$i</span>--) &#123;  </span><br><span class="line">            <span class="keyword">yield</span> <span class="variable">$i</span> =&gt; <span class="variable">$i</span> * <span class="variable">$i</span>; <span class="comment">//迭代生成数组： 键=》值  </span></span><br><span class="line">        &#125;  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;  </span><br><span class="line"><span class="keyword">foreach</span> (squares(<span class="number">3</span>, <span class="number">15</span>) <span class="keyword">as</span> <span class="variable">$n</span> =&gt; <span class="variable">$square</span>) &#123;  </span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$n</span> . ‘squared is‘ . <span class="variable">$square</span> . ‘&lt;br&gt;‘;  </span><br><span class="line">&#125;  </span><br><span class="line">输出：  </span><br><span class="line">    <span class="number">3</span> squared is <span class="number">9</span>  </span><br><span class="line">    <span class="number">4</span> squared is <span class="number">16</span>  </span><br><span class="line">    <span class="number">5</span> squared is <span class="number">25</span>  </span><br><span class="line">    ...  </span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>示例2：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">/对某一数组进行加权处理  </span><br><span class="line"><span class="variable">$numbers</span> = <span class="keyword">array</span>(‘nike‘ =&gt; <span class="number">200</span>, ‘jordan‘ =&gt; <span class="number">500</span>, ‘adiads‘ =&gt; <span class="number">800</span>);  </span><br><span class="line">  </span><br><span class="line"><span class="comment">//通常方法，如果是百万级别的访问量，这种方法会占用极大内存  </span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">rand_weight</span>(<span class="params"><span class="variable">$numbers</span></span>)  </span></span><br><span class="line"><span class="function"></span>&#123;  </span><br><span class="line">    <span class="variable">$total</span> = <span class="number">0</span>;  </span><br><span class="line">    <span class="keyword">foreach</span> (<span class="variable">$numbers</span> <span class="keyword">as</span> <span class="variable">$number</span> =&gt; <span class="variable">$weight</span>) &#123;  </span><br><span class="line">        <span class="variable">$total</span> += <span class="variable">$weight</span>;  </span><br><span class="line">        <span class="variable">$distribution</span>[<span class="variable">$number</span>] = <span class="variable">$total</span>;  </span><br><span class="line">    &#125;  </span><br><span class="line">    <span class="variable">$rand</span> = mt_rand(<span class="number">0</span>, <span class="variable">$total</span><span class="number">-1</span>);  </span><br><span class="line">  </span><br><span class="line">    <span class="keyword">foreach</span> (<span class="variable">$distribution</span> <span class="keyword">as</span> <span class="variable">$num</span> =&gt; <span class="variable">$weight</span>) &#123;  </span><br><span class="line">        <span class="keyword">if</span> (<span class="variable">$rand</span> &lt; <span class="variable">$weight</span>) <span class="keyword">return</span> <span class="variable">$num</span>;  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line"><span class="comment">//改用yield生成器  </span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">mt_rand_weight</span>(<span class="params"><span class="variable">$numbers</span></span>) </span>&#123;  </span><br><span class="line">    <span class="variable">$total</span> = <span class="number">0</span>;  </span><br><span class="line">    <span class="keyword">foreach</span> (<span class="variable">$numbers</span> <span class="keyword">as</span> <span class="variable">$number</span> =&gt; <span class="variable">$weight</span>) &#123;  </span><br><span class="line">        <span class="variable">$total</span> += <span class="variable">$weight</span>;  </span><br><span class="line">        <span class="keyword">yield</span> <span class="variable">$number</span> =&gt; <span class="variable">$total</span>;  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;  </span><br><span class="line">  </span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">mt_rand_generator</span>(<span class="params"><span class="variable">$numbers</span></span>)  </span></span><br><span class="line"><span class="function"></span>&#123;  </span><br><span class="line">    <span class="variable">$total</span> = array_sum(<span class="variable">$numbers</span>);  </span><br><span class="line">    <span class="variable">$rand</span> = mt_rand(<span class="number">0</span>, <span class="variable">$total</span> <span class="number">-1</span>);  </span><br><span class="line">    <span class="keyword">foreach</span> (mt_rand_weight(<span class="variable">$numbers</span>) <span class="keyword">as</span> <span class="variable">$num</span> =&gt; <span class="variable">$weight</span>) &#123;  </span><br><span class="line">        <span class="keyword">if</span> (<span class="variable">$rand</span> &lt; <span class="variable">$weight</span>) <span class="keyword">return</span> <span class="variable">$num</span>;  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;  </span><br><span class="line"></span><br></pre></td></tr></table></figure>
            </div>

            

            
                <ul class="post-tags-box">
                    
                        <li class="tag-item">
                            <a href="/tags/PHP/">#PHP</a>&nbsp;
                        </li>
                    
                </ul>
            

            
                <div class="article-nav">
                    
                        <div class="article-prev">
                            <a class="prev"
                               rel="prev"
                               href="/2021/06/21/swoole/"
                            >
                            <span class="left arrow-icon flex-center">
                              <i class="fas fa-chevron-left"></i>
                            </span>
                                <span class="title flex-center">
                                <span class="post-nav-title-item">1.1安装swoole</span>
                                <span class="post-nav-item">Prev posts</span>
                            </span>
                            </a>
                        </div>
                    
                    
                        <div class="article-next">
                            <a class="next"
                               rel="next"
                               href="/2021/06/09/tp5-%E4%BA%8B%E5%8A%A1%E5%86%85%E5%A4%9A%E7%A7%8Dsql%E6%96%B9%E6%B3%95%E9%94%99%E8%AF%AF/"
                            >
                            <span class="title flex-center">
                                <span class="post-nav-title-item">tp5 事务内多种sql方法错误</span>
                                <span class="post-nav-item">Next posts</span>
                            </span>
                                <span class="right arrow-icon flex-center">
                              <i class="fas fa-chevron-right"></i>
                            </span>
                            </a>
                        </div>
                    
                </div>
            

            
                <div class="comment-container">
                    
<div class="comments-container">
    <div id="comments-anchor"></div>
    <div class="comment-area-title">
        <i class="fas fa-comments"></i>&nbsp;Comments
    </div>
    
        
            

    <div class="valine-container">
        <script data-pjax src="//cdn.jsdelivr.net/npm/valine@latest/dist/Valine.min.js"></script>
        <div id="vcomments"></div>
        <script data-pjax>
          function loadValine() {
            new Valine({
              el: '#vcomments',
              appId: 'v7SvjMu6zFX3LPmiYGos39qx-gzGzoHsz',
              appKey: 'MlLOMElKkabjL3SHiqXhFWAW',
              meta: ['nick', 'mail', 'link'],
              avatar: 'wavatar',
              enableQQ: true,
              placeholder: '',
              lang: 'en'.toLowerCase()
            });

            function getAuthor(language) {
              switch (language) {
                case 'en':
                  return 'Author';
                case 'zh-CN':
                  return '博主';
                default:
                  return 'Master';
              }
            }

            // Add "Author" identify
            const getValineDomTimer = setInterval(() => {
              const vcards = document.querySelectorAll('#vcomments .vcards .vcard');
              if (vcards.length > 0) {
                let author = 'anlondon';

                if (author) {
                  for (let vcard of vcards) {
                    const vnick_dom = vcard.querySelector('.vhead .vnick');
                    const vnick = vnick_dom.innerHTML;
                    if (vnick === author) {
                      vnick_dom.innerHTML = `${vnick} <span class="author">${getAuthor(KEEP.hexo_config.language)}</span>`
                    }
                  }
                }
                clearInterval(getValineDomTimer);
              } else {
                clearInterval(getValineDomTimer);
              }
            }, 2000);
          }

          if ('true' === 'true') {
            const loadValineTimeout = setTimeout(() => {
              loadValine();
              clearTimeout(loadValineTimeout);
            }, 1000);
          } else {
            window.addEventListener('DOMContentLoaded', loadValine);
          }
        </script>
    </div>



        
    
</div>

                </div>
            
        </div>

        
            <div class="toc-content-container">
                <div class="post-toc-wrap">
    <div class="post-toc">
        <ol class="nav"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BC%98%E7%82%B9"><span class="nav-number">1.</span> <span class="nav-text">优点</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%A6%82%E5%BF%B5%E5%BC%95%E5%85%A5"><span class="nav-number">2.</span> <span class="nav-text">概念引入</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%80%9D%E8%80%83%E4%B8%80%E4%B8%AA%E9%97%AE%E9%A2%98"><span class="nav-number">3.</span> <span class="nav-text">思考一个问题</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%88%9B%E5%BB%BA%E7%94%9F%E6%88%90%E5%99%A8"><span class="nav-number">4.</span> <span class="nav-text">创建生成器</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E7%94%9F%E6%88%90%E5%99%A8"><span class="nav-number">5.</span> <span class="nav-text">使用生成器</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E7%94%9F%E6%88%90%E5%99%A8"><span class="nav-number">6.</span> <span class="nav-text">深入理解生成器</span></a><ol class="nav-child"><li class="nav-item nav-level-6"><a class="nav-link" href="#%E4%BB%A3%E7%A0%81%E5%89%96%E6%9E%90"><span class="nav-number">6.0.1.</span> <span class="nav-text">代码剖析</span></a></li></ol></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%A6%82%E5%BF%B5%E7%90%86%E8%A7%A3"><span class="nav-number">7.</span> <span class="nav-text">概念理解</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%AE%9E%E9%99%85%E5%BC%80%E5%8F%91%E5%BA%94%E7%94%A8"><span class="nav-number">8.</span> <span class="nav-text">实际开发应用</span></a><ol class="nav-child"><li class="nav-item nav-level-6"><a class="nav-link" href="#%E8%AF%BB%E5%8F%96%E8%B6%85%E5%A4%A7%E6%96%87%E4%BB%B6"><span class="nav-number">8.0.1.</span> <span class="nav-text">读取超大文件</span></a></li></ol></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%A1%A5%E5%85%85"><span class="nav-number">9.</span> <span class="nav-text">补充</span></a></li></ol>
    </div>
</div>

            </div>
        
    </div>
</div>


                
            </div>

        </div>

        <div class="page-main-content-bottom">
            
<footer class="footer">
    <div class="info-container">
        <div class="copyright-info info-item">
            &copy;
            
                <span>2020</span> -
            
            2023
            
                &nbsp;<i class="fas fa-heart icon-animate"></i>
                &nbsp;<a href="/">anlondon</a>
            
        </div>
        
            <script async data-pjax
                    src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
            <div class="website-count info-item">
                
                    Visitor Count&nbsp;<span id="busuanzi_value_site_uv"></span>&ensp;
                
                
                    Totalview&nbsp;<span id="busuanzi_value_site_pv"></span>
                
            </div>
        
        <div class="theme-info info-item">
            Powered by <a target="_blank" href="https://hexo.io">Hexo</a>&nbsp;|&nbsp;Theme&nbsp;<a class="theme-version" target="_blank" href="https://github.com/XPoet/hexo-theme-keep">Keep v3.5.2</a>
        </div>
        
            <div class="icp-info info-item">
                <a target="_blank" rel="nofollow"
                   href="https://beian.miit.gov.cn"
                >
                    蜀ICP备2021002582号
                </a>

                <a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=51010602001866" style="display:inline-block;text-decoration:none;height:17px;line-height:17px;">
                    <img src="https://www.beian.gov.cn/img/new/gongan.png" style="float:left;"/>
                    <p style="float:left;height:20px;line-height:20px;margin: 0px 0px 0px 5px;">川公网安备 51010602001866号</p>
                </a>

            </div>
        
        
    </div>
</footer>

        </div>
    </div>

    
        <div class="post-tools">
            <div class="post-tools-container">
    <ul class="tools-list">
        <!-- TOC aside toggle -->
        
            <li class="tools-item flex-center toggle-show-toc">
                <i class="fas fa-list"></i>
            </li>
        

        <!-- go comment -->
        
            <li class="tools-item flex-center go-to-comments">
                <i class="fas fa-comment"></i>
                <span class="post-comments-count"></span>
            </li>
        
    </ul>
</div>

        </div>
    

    <div class="right-bottom-side-tools">
        <div class="side-tools-container">
    <ul class="side-tools-list">
        <li class="tools-item tool-font-adjust-plus flex-center">
            <i class="fas fa-search-plus"></i>
        </li>

        <li class="tools-item tool-font-adjust-minus flex-center">
            <i class="fas fa-search-minus"></i>
        </li>

        <li class="tools-item tool-dark-light-toggle flex-center">
            <i class="fas fa-moon"></i>
        </li>

        <!-- rss -->
        

        
            <li class="tools-item tool-scroll-to-top flex-center">
                <i class="fas fa-arrow-up"></i>
            </li>
        

        <li class="tools-item tool-scroll-to-bottom flex-center">
            <i class="fas fa-arrow-down"></i>
        </li>
    </ul>

    <ul class="exposed-tools-list">
        <li class="tools-item tool-toggle-show flex-center">
            <i class="fas fa-cog fa-spin"></i>
        </li>
        
    </ul>
</div>

    </div>

    <div class="zoom-in-image-mask">
    <img class="zoom-in-image">
</div>


    
        <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
          <span class="search-input-field-pre">
            <i class="fas fa-keyboard"></i>
          </span>
            <div class="search-input-container">
                <input autocomplete="off"
                       autocorrect="off"
                       autocapitalize="off"
                       placeholder="Search..."
                       spellcheck="false"
                       type="search"
                       class="search-input"
                >
            </div>
            <span class="close-popup-btn">
                <i class="fas fa-times"></i>
            </span>
        </div>
        <div id="search-result">
            <div id="no-result">
                <i class="fas fa-spinner fa-pulse fa-5x fa-fw"></i>
            </div>
        </div>
    </div>
</div>

    

</main>




<script src="/js/utils.js"></script>

<script src="/js/main.js"></script>

<script src="/js/header-shrink.js"></script>

<script src="/js/back2top.js"></script>

<script src="/js/dark-light-toggle.js"></script>





    
<script src="/js/local-search.js"></script>




    
<script src="/js/code-block.js"></script>




    
<script src="/js/lazyload.js"></script>



<div class="post-scripts pjax">
    
        
<script src="/js/post-helper.js"></script>

        
            
<script src="/js/libs/anime.min.js"></script>

        
        
            
<script src="/js/toc.js"></script>

        
    
</div>


    
<script src="/js/libs/pjax.min.js"></script>

<script>
    window.addEventListener('DOMContentLoaded', () => {
        window.pjax = new Pjax({
            selectors: [
                'head title',
                '.page-container',
                '.pjax'
            ],
            history: true,
            debug: false,
            cacheBust: false,
            timeout: 0,
            analytics: false,
            currentUrlFullReload: false,
            scrollRestoration: false,
            // scrollTo: true,
        });

        document.addEventListener('pjax:send', () => {
            KEEP.utils.pjaxProgressBarStart();
        });

        document.addEventListener('pjax:complete', () => {
            KEEP.utils.pjaxProgressBarEnd();
            window.pjax.executeScripts(document.querySelectorAll('script[data-pjax], .pjax script'));
            KEEP.refresh();
        });
    });
</script>



</body>
</html>
